package com.example.ddd.application.service;

import com.example.ddd.application.assembler.ProductAssembler;
import com.example.ddd.application.dto.ProductDTO;
import com.example.ddd.domain.model.entity.Product;
import com.example.ddd.domain.repository.ProductRepository;
import com.example.ddd.domain.service.ProductDomainService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ProductApplicationService {
    private final ProductRepository productRepository;
    private final ProductDomainService productDomainService;
    private final ProductAssembler productAssembler;
    
    @Transactional
    public ProductDTO createProduct(ProductDTO productDTO) {
        Product product = productAssembler.toEntity(productDTO);
        Product savedProduct = productDomainService.createProduct(product);
        return productAssembler.toDTO(savedProduct);
    }
    
    @Transactional(readOnly = true)
    public Optional<ProductDTO> getProductById(Long id) {
        return productRepository.findById(id)
                .map(productAssembler::toDTO);
    }
    
    @Transactional(readOnly = true)
    public List<ProductDTO> getAllProducts() {
        return productRepository.findAll().stream()
                .map(productAssembler::toDTO)
                .collect(Collectors.toList());
    }
    
    @Transactional
    public Optional<ProductDTO> updateProduct(Long id, ProductDTO productDTO) {
        return productRepository.findById(id)
                .map(existingProduct -> {
                    existingProduct.setName(productDTO.getName());
                    existingProduct.setDescription(productDTO.getDescription());
                    existingProduct.setPrice(productDTO.getPrice());
                    existingProduct.setStock(productDTO.getStock());
                    return productRepository.save(existingProduct);
                })
                .map(productAssembler::toDTO);
    }
    
    @Transactional
    public void deleteProduct(Long id) {
        productRepository.deleteById(id);
    }
}